package com.bigflexlib.x.mx.collections.IList.op
{

	import flash.utils.Dictionary;
	
	import mx.collections.IList;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	
	import com.bigflexlib.core.markers.IIncomplete;
	import com.bigflexlib.x.mx.collections.IList.IListUtil;


	public class ListStrictDistinctOp extends AbstractListOp implements IIncomplete
	{
		
		
		private var dict:Dictionary;
		
		private var output:IList;

		
		public function ListStrictDistinctOp( list:IList, output:IList )
		{
			
			super( list );

			this.output = output;
			
			dict = new Dictionary( );


			IListUtil.autoUpdate( output, false );	

				output.removeAll();
				
				add( list.toArray( ) );			

			IListUtil.autoUpdate( output, true );	
		
		}		
		
		
		
		
		override public function dispose( ):void
		{
			
			super.dispose( );
			
			output = null;
		
			dict = null;
		
		}
		
		
		
		
		
		override protected function iList_collectionChange( event:CollectionEvent ):void
		{
		
			
			IListUtil.autoUpdate( output, false );		
			
			
	        switch ( event.kind )
	        {
	            
	            case CollectionEventKind.ADD:
				
					add( event.items );
						            
	            break;
	            
	            
	            
	            case CollectionEventKind.REMOVE:
					
					remove( event.items );				
	            
	            break;

	
	            case CollectionEventKind.RESET:

					refresh( );

	            break;



	            case CollectionEventKind.REFRESH:

	                refresh( );

	            break;

	
	        }
	        
			IListUtil.autoUpdate( output, true );	
		
		
		
		}


		
		
		private function refresh( ):void
		{
					
		}
		
		
		
		/**
		 * 
		 * returns ( and optionally manipulates ) the multiplicity
		 * of the item in the dictionary
		 * 
		 * @param item
		 * @param delta
		 * @return 
		 * 
		 */		
		private function m( item:*, delta:int=0 ):int
		{
		
			if ( ! dict[ item ] ) 
			{
				dict[ item ] = 0;
			}
				
			
			
			if ( delta != 0 )
			{
				var n:int = dict[ item ] as int;
				n = n + delta;
				dict[ item ] = n;
				return n;		
			}
			
			
			return dict[ item ] as int; 
			
		}





	
		private function remove( items:Array ):void
		{
			for each ( var item:Object in items )
			{
				if ( m( item , -1 ) == 0 )
				{
					// remove from the output
					var indexInOutput:int = IListUtil.getItemIndex( output, item );
					output.removeItemAt( indexInOutput );				
				}
			}
		}
		




		private function add( items:Array ):void
		{
			for each ( var item:Object in items )
			{
				if ( m( item, 1 ) == 1 ) // only add if we have no equivalent copies
				{
					output.addItem( item );				
				}
			}
		}		
		
		
		
		
		
		
		
		
		
	}
}